home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
rpg
/
crossfir.000
/
crossfir
/
crossfire-0.92.4.client
/
commands.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-21
|
10KB
|
359 lines
/* Handles commands received by the server. This does not necessarily
* handle all commands - some might be in other files (like init.c)
*
* this file contains most of the commands for the dispatch loop most of
* the functions are self-explanatory, the pixmap/bitmap commands recieve
* the picture, and display it. The drawinfo command draws a string
* in the info window, the stats command updates the local copy of the stats
* and displays it. handle_query prompts the user for input.
* send_reply sends off the reply for the input.
* player command gets the player information.
* ItemCmd grabs and display information for items in the inventory
* MapScroll scrolls the map on the client by some amount
* MapCmd displays the map either with layer packing or stack packing.
* packing/unpacking is best understood by looking at the server code
* (server/ericserver.c)
* stack packing is easy, for every map entry that changed, we pack
* 1 byte for the x/y location, 1 byte for the count, and 2 bytes per
* face in the stack.
* layer packing is harder, but I seem to remember more efficient:
* first we pack in a list of all map cells that changed and are now
* empty. The end of this list is a 255, which is bigger that 121, the
* maximum packed map location.
* For each changed location we also pack in a list of all the faces and
* X/Y coordinates by layer, where the layer is the depth in the map.
* This essentially takes slices through the map rather than stacks.
* Then for each layer, (max is MAXMAPCELLFACES, a bad name) we start
* packing the layer into the message. First we pack in a face, then
* for each place on the layer with the same face, we pack in the x/y
* location. We mark the last x/y location with the high bit on
* (11*11 = 121 < 128). We then continue on with the next face, which
* is why the code marks the faces as -1 if they are finished. Finally
* we mark the last face in the layer again with the high bit, clearly
* limiting the total number of faces to 32767, the code comments it's
* 16384, I'm not clear why, but the second bit may be used somewhere
* else as well.
* The unpacking routines basically perform the opposite operations.
*/
#include <client.h>
#include <X11/Xlib.h>
/* these are just dummy functions for right now */
void look_at(int x, int y) {}
void PrintMsg(ArgList msg)
{
printf("Command: %s\n",ArgList_getString(msg,1));
}
void PixMapCmd(ArgList msg)
{
char *buf;
unsigned long buflen;
/* printf("Recieveing Pixmap #%ld\n",ArgList_getLong(msg,2));*/
buf = ArgList_getBuf(msg,3,&buflen);
/* printf("%s\n",buf);*/
display_newpixmap(ArgList_getLong(msg,2),buf,buflen);
}
void BitMapCmd(ArgList msg)
{
char *buf;
unsigned long buflen;
long num = ArgList_getLong(msg,2);
long fg = ArgList_getChar(msg,3);
long bg = ArgList_getChar(msg,4);
/* printf("Recieveing Pixmap #%ld\n",ArgList_getLong(msg,2));*/
buf = ArgList_getBuf(msg,5,&buflen);
if (buflen != 24*3) {
fprintf(stderr,"Incorrect length on bitmap buffer should be %d was %ld\n",
24*3,buflen);
abort();
}
/* printf("%s\n",buf);*/
display_newbitmap(num,fg,bg,buf);
}
void DrawInfoCmd(ArgList msg)
{
int color=ArgList_getChar(msg,2);
/* printf("Draw_info: %s\n",ArgList_getString(msg,3));*/
if (color!=NDI_BLACK)
draw_color_info(color, ArgList_getString(msg,3));
else
draw_info(ArgList_getString(msg,3),NDI_BLACK);
}
void StatsCmd(ArgList msg)
{
int i,m;
int c;
m = ArgList_getLength(msg);
for(i=2;i<m;i+=2) {
c = ArgList_getChar(msg,i);
switch (c) {
case CS_STAT_HP: cpl.stats.hp=ArgList_getLong(msg,i+1);break;
case CS_STAT_MAXHP:cpl.stats.maxhp=ArgList_getLong(msg,i+1);break;
case CS_STAT_SP: cpl.stats.sp=ArgList_getLong(msg,i+1);break;
case CS_STAT_MAXSP:cpl.stats.maxsp=ArgList_getLong(msg,i+1);break;
case CS_STAT_STR: cpl.stats.Str=ArgList_getLong(msg,i+1);break;
case CS_STAT_INT: cpl.stats.Int=ArgList_getLong(msg,i+1);break;
case CS_STAT_WIS: cpl.stats.Wis=ArgList_getLong(msg,i+1);break;
case CS_STAT_DEX: cpl.stats.Dex=ArgList_getLong(msg,i+1);break;
case CS_STAT_CON: cpl.stats.Con=ArgList_getLong(msg,i+1);break;
case CS_STAT_CHA: cpl.stats.Cha=ArgList_getLong(msg,i+1);break;
case CS_STAT_EXP: cpl.stats.exp=ArgList_getLong(msg,i+1);break;
case CS_STAT_LEVEL:cpl.stats.level=ArgList_getLong(msg,i+1);break;
case CS_STAT_WC: cpl.stats.wc=ArgList_getLong(msg,i+1);break;
case CS_STAT_AC: cpl.stats.ac=ArgList_getLong(msg,i+1);break;
case CS_STAT_DAM: cpl.stats.dam=ArgList_getLong(msg,i+1);break;
case CS_STAT_ARMOUR:cpl.stats.armor=ArgList_getLong(msg,i+1);break;
case CS_STAT_SPEED: cpl.stats.speed=ArgList_getLong(msg,i+1);break;
case CS_STAT_FOOD: cpl.stats.food=ArgList_getLong(msg,i+1);break;
case CS_STAT_WEAP_SP:cpl.stats.weapon_sp=ArgList_getLong(msg,i+1);break;
case CS_STAT_POW: cpl.stats.Pow=ArgList_getLong(msg,i+1);break;
case CS_STAT_GRACE:cpl.stats.grace=ArgList_getLong(msg,i+1);break;
case CS_STAT_MAXGRACE:cpl.stats.maxgrace=ArgList_getLong(msg,i+1);break;
case CS_STAT_RANGE: {
strcpy(cpl.range,ArgList_getString(msg, i+1));
break;
}
case CS_STAT_TITLE: {
strcpy(cpl.title,ArgList_getString(msg, i+1));
break;
}
default:
printf("Unknown stat number %d\n",c);
}
}
draw_stats(0);
draw_message_window(0);
}
void handle_query (ArgList msg)
{
char *buf2;
uint8 flags = ArgList_getChar(msg, 2);
buf2 = ArgList_getString(msg,3);
/* If we just get passed an empty string, why draw this? */
if (*buf2) draw_prompt(buf2);
/* Yes/no - don't do anything with it now */
if (flags & CS_QUERY_YESNO) {}
/* one character response expected */
if (flags & CS_QUERY_SINGLECHAR)
cpl.input_state = Reply_One;
else
cpl.input_state = Reply_Many;
if (flags & CS_QUERY_HIDEINPUT) /* no echo */
cpl.no_echo=1;
fprintf(stderr,"Received query. Input state now %d\n", cpl.input_state);
}
/* Sends a reply to the server. text contains the null terminated
* string of text to send. This function basically just packs
* the stuff up.
*/
void send_reply(char *text)
{
ArgList msg;
msg = ArgList_create();
ArgList_addLong(msg, STRINGCOMMAND);
ArgList_addString(msg,"reply");
ArgList_addString(msg,text);
ArgList_send(conns[0], msg);
ArgList_destroy(msg);
}
#define GET_LONG(p,l) ((l) = (unsigned long)(*(p)++ & 0xFF) << 24,\
(l) += (unsigned long)(*(p)++ & 0xFF) << 16,\
(l) += (unsigned long)(*(p)++ & 0xFF) << 8,\
(l) += (unsigned long)(*(p)++ & 0xFF))
#define GET_STRING(p,s) (strcpy(s,p), p+=strlen(p)+1)
/* This function copies relevant data from the archetype to the
* object. Only copies data that was not set in the object
* structure.
*
*/
void PlayerCmd(ArgList msg)
{
char name[MAX_BUF], *ptr;
long tag, weight, face;
ptr = ArgList_getBuf (msg, 2, NULL);
/* The only really needed thing is a tag, but sending some other
* information can be sended in same time
*/
GET_LONG(ptr, tag);
GET_LONG(ptr, weight);
GET_LONG(ptr, face);
GET_STRING(ptr, name);
new_player(tag, name, weight, face);
}
void item_actions (item *op)
{
if (op->open) {
open_container (op);
} else if (op->was_open) {
close_container (op);
}
/*
if (op->env == cpl.below) {
check_auto_pickup (op);
}
*/
}
void ItemCmd(ArgList msg)
{
long weight, loc, tag, face, flags, len;
char name[MAX_BUF], *endptr, *ptr;
ptr = ArgList_getBuf (msg, 2, &len);
endptr = ptr + len;
GET_LONG(ptr, loc);
if (ptr == endptr)
/* An empty item command can be used to delete the whole
* inventory of item 'loc'. Esspecially if loc is 0, then
* there is no floor under the player.
*/
delete_item_inventory(loc);
else if (loc < 0) { /* delele following items */
while (ptr < endptr) {
GET_LONG(ptr, tag);
delete_item(tag);
}
} else {
while (ptr < endptr) {
GET_LONG(ptr, tag);
GET_LONG(ptr, flags);
GET_LONG(ptr, weight);
GET_LONG(ptr, face);
GET_STRING(ptr, name);
if (flags & 0x0100) /* tmp. solution, clear the inventory */
delete_item_inventory(loc); /* deletes all items */
update_item (tag, loc, name, weight, face, flags);
item_actions (locate_item(tag));
}
}
/* draw_lists ();*/
}
void Map_unpackstack(unsigned char *cur,unsigned char *end)
{
long x,y,face,nfaces;
while(cur < end) {
x = (*cur >> 4) & 0x0F;
y = (*cur) & 0x0F;
cur++;
nfaces = *cur;
cur++;
display_map_clearcell(x,y);
while(nfaces>0) {
face = *cur << 8;
cur++;
face |= *cur;
cur++;
display_map_addbelow(x,y,face);
nfaces--;
}
}
}
void Map_unpacklayer(unsigned char *cur,unsigned char *end)
{
long x,y,face;
int xy;
int clear = 1;
unsigned char *fcur;
while (cur < end && *cur != 255) {
xy = *cur;
cur++;
x = xy / 11;
y = xy % 11;
display_map_clearcell(x,y);
}
cur++;
while(cur < end) {
fcur = cur;
face = *cur & 0x7f;
cur++;
face = (face << 8) | *cur;
cur++;
while(1) {
xy = *cur & 0x7f;
x = xy / 11;
y = xy % 11;
if (clear) {
display_map_clearcell(x,y);
}
display_map_addbelow(x,y,face);
xy = *cur;
cur++;
if (xy & 128) {
break;
}
if (cur==end) {
fprintf(stderr,"Incorrectly packed map.\n");
abort();
}
}
if (*fcur & 128)
clear = 0; /* end of first layer (or some layer after the first) */
}
}
void MapCmd(ArgList msg)
{
unsigned char *buf,*end;
unsigned long buflen;
/* printf("Recieving map\n");*/
buf = ArgList_getBuf(msg,2,&buflen);
end = buf + buflen;
display_map_startupdate();
#if 1
Map_unpacklayer(buf,end);
#else
Map_unpackstack(buf,end);
#endif
display_map_doneupdate();
}
void map_scrollCmd(ArgList msg)
{
int dx,dy;
dx = ArgList_getLong(msg,2);
dy = ArgList_getLong(msg,3);
display_mapscroll(dx,dy);
}